﻿#include "DateTime.h"

DateTime::DateTime()
{
	m_year = 1900;
	m_month = 1;
	m_day = 1;
	m_hour = 0;
	m_minute = 0;
	m_second = 0;
	m_mic_second = 0;
}

DateTime::DateTime(int y, int m, int d, int h, int M, int s)
{
	m_year = y;
	m_month = m;
	m_day = d;
	m_hour = h;
	m_minute = M;
	m_second = s;
	m_mic_second = 0;

	m_year = m_year <= 0 ? 1900 : m_year;
	m_month = m_month <= 0 ? 1 : m_month;
	m_day = m_day <= 0 ? 1 : m_day;
}

DateTime::~DateTime()
{
}

int DateTime::GetYear()
{
	return m_year;
}

int DateTime::GetMonth()
{
	return m_month;
}

int DateTime::GetDay()
{
	return m_day;
}

int DateTime::GetHour()
{
	return m_hour;
}

int DateTime::GetMinute()
{
	return m_minute;
}

int DateTime::GetSecond()
{
	return m_second;
}

int DateTime::GetMicSecond()
{
	return m_mic_second;
}

DateTime DateTime::Now()
{
	DateTime time;
	time.LocalTime();
	return time;
}

std::string DateTime::CurrentTime()
{
	DateTime time;
	time.LocalTime();
	return boost::str(boost::format("%02d:%02d:%02d") % time.GetHour() % time.GetMinute() % time.GetDay());
}

bool DateTime::BetweenTimeNow(std::string start, std::string stop)
{
	// 00:00:00
	std::string current = DateTime::CurrentTime();
	if (start == "" || start.length() != 8 ||
		stop == "" || stop.length() != 8)
	{
		return true;
	}
	if (strcmp(current.c_str(), start.c_str()) >= 0 &&
		strcmp(current.c_str(), stop.c_str()) <= 0)
	{
		return true;
	}
	return false;
}

DateTime DateTime::FromString(std::string time)
{
	DateTime date_time;
	date_time.From(time);
	return date_time;
}

std::string DateTime::GetLocalDay()
{
	return boost::gregorian::to_iso_string(boost::gregorian::day_clock::local_day());
}

std::string DateTime::GetLocalIOSTime()
{
	boost::posix_time::ptime ptime = boost::posix_time::microsec_clock::local_time();

	int y = ptime.date().year();
	int m = ptime.date().month();
	int d = ptime.date().day();
	int h = ptime.time_of_day().hours();
	int M = ptime.time_of_day().minutes();
	int S = ptime.time_of_day().seconds();
	uint64_t MM = ptime.time_of_day().fractional_seconds();
	while (MM > 1000)
	{
		MM /= 10;
	}

	boost::posix_time::ptime pt = boost::posix_time::microsec_clock::local_time();
	return boost::str(boost::format("%04d-%02d-%02dT%02d:%02d:%02d.%03d") % y % m % d % h % M % S % MM);
}

std::string DateTime::GetCurrentTime()
{
	std::string strPosixTime = boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time());

	strPosixTime.replace(4, 0, std::string("-"));
	strPosixTime.replace(7, 0, std::string("-"));

	size_t pos = strPosixTime.find('T');
	strPosixTime.replace(pos, 1, std::string(" "));
	strPosixTime.replace(pos + 3, 0, std::string(":"));
	strPosixTime.replace(pos + 6, 0, std::string(":"));
	return strPosixTime;
}

DateTime DateTime::Get(std::string time)
{
	DateTime dateUtil;
	if (!time.empty())
	{
		dateUtil.From(time);
	}
	return dateUtil;
}

DateTime DateTime::GetFromHHMMSS(std::string time)
{
	DateTime dateUtil;
	if (!time.empty())
	{
		dateUtil.FromNormalHHMMSS(time);
	}
	return dateUtil;
}

void DateTime::From(std::string time)
{
	// 无效字符
	if (time.empty())
	{
		return;
	}
	// 2013-01-30 23:32:22.000 o
	// 1900-Jan-01 00:00:00
	boost::posix_time::ptime pt;
	if (-1 == time.find("T"))
	{
		pt = boost::posix_time::time_from_string(time);
	}
	// 20201030T233222
	else
	{
		pt = boost::posix_time::from_iso_string(time);
	}
	Update(pt);
}

void DateTime::From(std::tm time)
{
	boost::posix_time::ptime pt = boost::posix_time::ptime_from_tm(time);
	Update(pt);
}

std::string DateTime::Transformat(std::string source, std::string sourcefmt, std::string destfmt)
{
	// %Y-%m-%dT%H:%M:%S%F
	//时间格式转换
	//%d/%m/%Y %H:%M:%S 到 %Y/%m/%d %H:%M:%S
	//%d/%m/%Y 到 %Y-%m-%d
	//%H:%M:%S 到 %H-%M-%S
	//10/06/2020 04:12:21 日期月日和时间必须为2位
	//sourcefmt 原日期格式
	//descfmt 转换后的格式
	//std::string sourcefmt = "%d/%m/%Y %H:%M:%S%F";
	//std::string strtime = "10/06/2020 04:12:21";

	auto infacet = std::locale(std::locale::classic(), new boost::posix_time::time_input_facet(sourcefmt));
	std::istringstream instr(source);
	instr.imbue(infacet);

	// 字符串转时间
	boost::posix_time::ptime pt;
	instr >> pt;

	//std::string descfmt = "%Y/%m/%d %H:%M:%S";
	auto outfacet = new boost::posix_time::time_facet(destfmt.c_str());

	std::stringstream outstr;
	outstr.imbue(std::locale(outstr.getloc(), outfacet));
	outstr.str("");

	// 时间转字符串
	outstr << pt;
	return outstr.str();
}

std::time_t DateTime::IOSTimeToTM(std::string time, std::string fmt)
{
	DateTime dt;
	dt.From(time, fmt);
	return dt.Totm();
}

std::time_t DateTime::Diff(DateTime begin, DateTime end)
{
	return end.Totm() - begin.Totm();
}

boost::chrono::system_clock::time_point DateTime::CurrrentTimePoint()
{
	return boost::chrono::system_clock::now();
}

double DateTime::Duration(boost::chrono::system_clock::time_point& start)
{
	// 获取结束时间
	boost::chrono::system_clock::time_point end = boost::chrono::system_clock::now();
	// 计算持续时间
	boost::chrono::duration<double> elapsed_seconds = end - start;
	// 时间点差值
	return elapsed_seconds.count();
}

void DateTime::From(std::string time, std::string fmt)
{
	if (time.empty())
	{
		return;
	}

	auto infacet = std::locale(std::locale::classic(), new boost::posix_time::time_input_facet(fmt));
	std::istringstream instr(time);
	instr.imbue(infacet);

	// 字符串转时间
	boost::posix_time::ptime pt;
	instr >> pt;
	Update(pt);
}

void DateTime::FromNormalHHMMSS(std::string time)
{
	if (time.empty())
	{
		return;
	}

	// %H:%M:%S
	auto infacet = std::locale(std::locale::classic(), new boost::posix_time::time_input_facet("%H:%M:%S"));
	std::istringstream instr(time);
	instr.imbue(infacet);

	// 字符串转时间
	boost::posix_time::ptime pt;
	instr >> pt;
	Update(pt);
}

void DateTime::From(time_t t)
{
	struct tm* p = localtime(&t);
	boost::posix_time::ptime pt = boost::posix_time::ptime_from_tm(*p);
	Update(pt);
}

#ifdef _WIN32
void DateTime::From(FILETIME ft)
{
	boost::posix_time::ptime pt = boost::posix_time::from_ftime<boost::posix_time::ptime>(ft);
	Update(pt);
}
#endif

bool DateTime::Equal(DateTime& time)
{
	return m_year == time.GetYear() && m_month == time.GetMonth() && m_day == time.GetDay() && m_hour == time.GetHour() && m_minute == time.GetMinute() && m_second == time.GetSecond();
}

bool DateTime::EqualDay(DateTime& time)
{
	return m_year == time.GetYear() && m_month == time.GetMonth() && m_day == time.GetDay();
}

bool DateTime::EqualTime(DateTime& time)
{
	return m_hour == time.GetHour() && m_minute == time.GetMinute() && m_second == time.GetSecond();
}

int DateTime::Compare(DateTime& DateUtil)
{
	//boost::posix_time::time_period tp1();
	return ToPTime() > DateUtil.ToPTime() ? 1 : 0;
}

void DateTime::Update(boost::posix_time::ptime ptime)
{
	m_year = ptime.date().year();
	m_month = ptime.date().month();
	m_day = ptime.date().day();
	m_hour = ptime.time_of_day().hours();
	m_minute = ptime.time_of_day().minutes();
	m_second = ptime.time_of_day().seconds();
	uint64_t MM = ptime.time_of_day().fractional_seconds();
	while (MM > 1000)
	{
		MM /= 10;
	}
	m_mic_second = MM;
}

void DateTime::UpdateDate(int y, int m, int d)
{
	m_year = y;
	m_month = m;
	m_day = d;

	m_year = m_year <= 0 ? 1900 : m_year;
	m_month = m_month <= 0 ? 1 : m_month;
	m_day = m_day <= 0 ? 1 : m_day;
}

void DateTime::UpDateUtil(int h, int m, int s)
{
	m_hour = h;
	m_minute = m;
	m_second = s;
}

void DateTime::UpdateDate(DateTime& date)
{
	m_year = date.GetYear();
	m_month = date.GetMonth();
	m_day = date.GetDay();

	m_year = m_year <= 0 ? 1900 : m_year;
	m_month = m_month <= 0 ? 1 : m_month;
	m_day = m_day <= 0 ? 1 : m_day;
}

void DateTime::UpDateUtil(DateTime& time)
{
	m_hour = time.GetHour();
	m_minute = time.GetMinute();
	m_second = time.GetSecond();
}

DateTime& DateTime::AddSeconds(int seconds)
{
	std::time_t cur = Totm();
	cur = cur + seconds;
	From(cur);
	return *this;
}

void DateTime::LocalTime()
{
	// second_clock::universal_time()
	// microsec_clock::local_time()
	// microsec_clock::universal_time()
	boost::posix_time::ptime time(boost::posix_time::second_clock::local_time());
	Update(time);
}

boost::posix_time::ptime DateTime::ToPTime()
{
	struct tm pt_tm;
	pt_tm.tm_year = m_year - 1900;
	pt_tm.tm_mon = m_month - 1;
	pt_tm.tm_mday = m_day;
	pt_tm.tm_hour = m_hour;
	pt_tm.tm_min = m_minute;
	pt_tm.tm_sec = m_second;

	return boost::posix_time::ptime_from_tm(pt_tm);
}

std::time_t DateTime::Totm()
{
	struct tm pt_tm;
	pt_tm.tm_year = m_year - 1900;
	pt_tm.tm_mon = m_month - 1;
	pt_tm.tm_mday = m_day;
	pt_tm.tm_hour = m_hour;
	pt_tm.tm_min = m_minute;
	pt_tm.tm_sec = m_second;
	return mktime(&pt_tm);
	//tm *  tm2 = localtime(&tt);
	//return boost::posix_time::to_time_t(ToPTime());
}

bool DateTime::Invalid()
{
	return m_year == 1900 && m_month == 1 && m_day == 1 && m_hour == 0 && m_minute == 0 && m_second == 0;
}

int DateTime::GetDayOfWeek()
{
	return ToPTime().date().day_of_week();
}

std::string DateTime::ToNormalString()
{
	std::string destfmt = "%Y-%m-%d %H:%M:%S";
	auto outfacet = new boost::posix_time::time_facet(destfmt.c_str());

	std::stringstream outstr;
	outstr.imbue(std::locale(outstr.getloc(), outfacet));
	outstr.str("");

	// 时间转字符串
	boost::posix_time::ptime pt = ToPTime();
	outstr << pt;
	return outstr.str();
}

std::string DateTime::ToNormalHHMMSS()
{
	std::string destfmt = "%H:%M:%S";
	auto outfacet = new boost::posix_time::time_facet(destfmt.c_str());

	std::stringstream outstr;
	outstr.imbue(std::locale(outstr.getloc(), outfacet));
	outstr.str("");

	// 时间转字符串
	boost::posix_time::ptime pt = ToPTime();
	outstr << pt;
	return outstr.str();
}

std::string DateTime::ToSimpleString()
{
	// https://www.cnblogs.com/lidabo/p/3938969.html
	// 1900-Jan-01 00:00:00
	return boost::posix_time::to_simple_string(ToPTime());
}

std::string DateTime::ToIOSString()
{
	//20201010T233210
	// https://www.cnblogs.com/lidabo/p/3938969.html
	return boost::posix_time::to_iso_string(ToPTime());
}

std::string DateTime::ToIOSExtString()
{
	// https://www.cnblogs.com/lidabo/p/3938969.html
	// YYYY-MM-DDTHH:MM:SS
	return boost::posix_time::to_iso_extended_string(ToPTime());
}